/**
 * Store标准化工具
 * 为Store提供标准化的方法和错误处理
 */

const dayjs = require('dayjs');
const cacheHelper = require('../../helpers/cache_helper.js');
import * as mobx from 'mobx-miniprogram';
import { configure } from 'mobx-miniprogram';

// 配置MobX，强制状态修改必须在actions内部执行，并提供更多调试信息
configure({
  enforceActions: 'observed', // 强制状态修改必须在actions内部执行
  computedRequiresReaction: true, // 计算属性需要观察者
  reactionRequiresObservable: true, // 反应需要可观察对象
  disableErrorBoundaries: false // 在错误边界内显示错误
});

// 使用全局console.error作为默认错误处理器
const defaultErrorLogger = (error, context) => {
  console.error(`[${context}]`, error);
};

/**
 * 标准Store基础方法
 * 被所有Store继承
 */
const BaseStoreMethods = {
  // 重置Store状态
  reset: function() {
    console.warn('reset方法必须由具体Store实现');
  },
  
  // 设置加载状态
  setLoading: function(key, status) {
    if (this.loading && typeof this.loading === 'object') {
      this.loading[key] = status;
    } else if (typeof key === 'boolean') {
      // 兼容旧代码
      this.loading = key;
    }
  },
  
  // 设置错误信息
  setError: function(error, module = 'global') {
    // 如果有分模块的错误结构
    if (this.error && typeof this.error === 'object' && this.error[module] !== undefined) {
      this.error[module] = error;
    } else {
      // 简单错误结构
      this.error = error;
    }
    
    // 记录到全局错误处理器
    if (error) {
      // 使用通用错误记录方式，避免直接依赖errorHandler
      if (typeof wx !== 'undefined' && wx.getSystemInfoSync) {
        console.error(`[Store:${this._storeName || 'Unknown'}]`, error);
      } else {
        defaultErrorLogger(error, `Store:${this._storeName || 'Unknown'}`);
      }
    }
  },
  
  // 清除错误信息
  clearError: function(module = 'global') {
    if (this.error && typeof this.error === 'object' && this.error[module] !== undefined) {
      this.error[module] = null;
    } else {
      this.error = null;
    }
  },
  
  // 缓存数据到本地
  _cacheData: function(data, key = this._cacheKey, time = 30) {
    if (!key) return false;
    
    try {
      // 保存数据和时间戳
      const cacheData = {
        data: data,
        time: dayjs().valueOf(),
        expire: time * 60 * 1000 // 转换为毫秒
      };
      
      cacheHelper.set(key, cacheData, time * 60);
      
      // 更新缓存信息
      if (this.cache) {
        this.cache.lastUpdate = dayjs().valueOf();
        this.cache.isExpired = false;
      }
      
      return true;
    } catch (e) {
      console.error(`[Store:${this._storeName || 'Unknown'}] 缓存数据失败`, e);
      return false;
    }
  },
  
  // 从缓存加载数据
  _loadFromCache: function(key = this._cacheKey) {
    if (!key) return null;
    
    try {
      const cacheData = cacheHelper.get(key);
      
      if (!cacheData || !cacheData.data) return null;
      
      // 检查是否过期
      const now = dayjs().valueOf();
      const isExpired = (now - cacheData.time) > cacheData.expire;
      
      // 更新缓存信息
      if (this.cache) {
        this.cache.lastUpdate = cacheData.time;
        this.cache.isExpired = isExpired;
      }
      
      return isExpired ? null : cacheData.data;
    } catch (e) {
      console.error(`[Store:${this._storeName || 'Unknown'}] 读取缓存失败`, e);
      return null;
    }
  },
  
  // 清除缓存
  clearCache: function(key = this._cacheKey) {
    if (!key) return;
    
    try {
      cacheHelper.remove(key);
      
      // 重置缓存信息
      if (this.cache) {
        this.cache.lastUpdate = null;
        this.cache.isExpired = true;
      }
    } catch (e) {
      console.error(`[Store:${this._storeName || 'Unknown'}] 清除缓存失败`, e);
    }
  },
  
  // 设置自动刷新定时器
  _setupAutoRefresh: function(interval = 5) {
    this._clearAutoRefresh(); // 先清除已有定时器
    
    if (interval <= 0) return;
    
    // 设置定时刷新
    this._refreshTimer = setInterval(() => {
      // 检查是否需要刷新数据
      if (this.cache && this.cache.isExpired) {
        // 具体刷新逻辑由各Store实现
        if (typeof this.refresh === 'function') {
          this.refresh();
        }
      }
    }, interval * 60 * 1000); // 转换为毫秒
  },
  
  // 清除自动刷新定时器
  _clearAutoRefresh: function() {
    if (this._refreshTimer) {
      clearInterval(this._refreshTimer);
      this._refreshTimer = null;
    }
  },
  
  // 安全执行API调用(带错误处理)
  _safeCall: async function(apiFunc, params = {}, loadingKey = 'loading') {
    if (!apiFunc) return null;
    
    // 设置加载状态
    this.setLoading(loadingKey, true);
    this.clearError();
    
    try {
      const result = await apiFunc(params);
      return result;
    } catch (error) {
      this.setError(error);
      return null;
    } finally {
      this.setLoading(loadingKey, false);
    }
  },
  
  // 格式化日期
  formatDate: function(date, format = 'YYYY-MM-DD') {
    if (!date) return '';
    return dayjs(date).format(format);
  },
  
  // 格式化时间
  formatTime: function(date, format = 'YYYY-MM-DD HH:mm:ss') {
    if (!date) return '';
    return dayjs(date).format(format);
  },
  
  // 获取相对时间 (例如: "3小时前")
  fromNow: function(date) {
    if (!date) return '';
    return dayjs(date).fromNow();
  }
};

/**
 * 标准化Store
 * @param {Object} store MobX Store实例
 * @param {string} name Store名称
 * @param {string} cacheKey 缓存键名
 * @returns {Object} 标准化后的Store
 */
function standardizeStore(store, name, cacheKey) {
  // 保存元数据
  store._storeName = name;
  store._cacheKey = cacheKey;
  
  // 合并基础方法
  for (const methodName in BaseStoreMethods) {
    // 如果Store已有此方法，则不覆盖
    if (typeof store[methodName] === 'function') continue;
    
    // 合并方法
    store[methodName] = BaseStoreMethods[methodName].bind(store);
  }
  
  // 确保必要的数据结构
  if (!store.loading) store.loading = {};
  if (!store.error) store.error = null;
  if (!store.cache) {
    store.cache = {
      lastUpdate: null,
      isExpired: true,
      autoRefreshInterval: 5 // 默认5分钟
    };
  }
  
  return store;
}

/**
 * 标准化全局Store
 * @param {Object} store MobX Store实例
 * @param {string} name Store名称
 * @returns {Object} 标准化后的Store
 */
function standardizeGlobalStore(store, name) {
  // 确保store至少有reset方法用于重置状态
  if (!store.reset) {
    console.warn(`Store ${name} 缺少reset方法，已自动添加`);
    // 使用安全的方式创建reset方法，避免直接依赖mobx.action
    try {
      if (typeof mobx.action === 'function') {
        store.reset = mobx.action(function() {
          console.log(`重置 ${name} store`);
          // 实现通用的重置逻辑，具体store可能需要覆盖此方法
        });
      } else {
        // 如果mobx.action不可用，直接使用普通函数
        store.reset = function() {
          console.log(`重置 ${name} store`);
          // 实现通用的重置逻辑，具体store可能需要覆盖此方法
        };
      }
    } catch (error) {
      console.error(`为 ${name} 创建reset方法失败，使用普通函数`, error);
      store.reset = function() {
        console.log(`重置 ${name} store`);
      };
    }
  }

  // 记录所有action的执行
  const originalActions = {};
  
  // 遍历所有方法，包装actions以添加日志和错误处理
  Object.keys(store).forEach(key => {
    const prop = store[key];
    
    // 只处理函数类型的属性
    if (typeof prop === 'function' && key !== 'reset') {
      originalActions[key] = prop;
      
      // 重写方法，添加日志和错误处理
      store[key] = function(...args) {
        try {
          console.log(`执行 ${name}.${key}() 方法，参数:`, args.length ? args : '无');
          const result = originalActions[key].apply(this, args);
          
          // 如果是Promise，添加错误处理
          if (result && typeof result.then === 'function') {
            return result.catch(error => {
              console.error(`${name}.${key}() 异步执行出错:`, error);
              throw error;
            });
          }
          
          return result;
        } catch (error) {
          console.error(`${name}.${key}() 执行出错:`, error);
          throw error;
        }
      };
    }
  });

  // 添加更新检查方法
  if (!store._checkUpdates) {
    store._checkUpdates = function(prevState, nextState, fieldName) {
      if (prevState === nextState) {
        console.warn(`${name} 状态字段 ${fieldName} 没有变化，可能没有正确更新`);
        return false;
      }
      return true;
    };
  }

  // 添加调试信息
  store._storeName = name;
  store._isStandardized = true;
  store._debug = function() {
    console.log(`${name} Store 当前状态:`, JSON.stringify(this));
  };

  return store;
}

/**
 * 标准化模块Store
 * @param {Object} store MobX Store实例
 * @param {string} module 模块名
 * @param {string} name Store名称
 * @returns {Object} 标准化后的Store
 */
function standardizeModuleStore(store, module, name) {
  // 首先应用全局标准化
  const standardized = standardizeGlobalStore(store, name);
  
  // 模块特定检查
  // 检查模块store是否有必要的加载状态字段
  if (!standardized.loading) {
    console.warn(`模块 ${module} store缺少loading字段`);
    standardized.loading = { list: false, detail: false, update: false };
  }
  
  // 检查模块store是否有必要的错误处理字段
  if (!standardized.error) {
    console.warn(`模块 ${module} store缺少error字段`);
    standardized.error = { list: null, detail: null, update: null };
  }

  return standardized;
}

module.exports = {
  standardizeStore,
  standardizeGlobalStore,
  standardizeModuleStore,
  BaseStoreMethods
}; 